<?php

use Monolog\Logger as MonologLogger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;

class Logger
{
    const LOG_DIRECTORY = '/data/wwwroot/log/qingtai';
    //const LOG_DIRECTORY = '/Users/xiongrenhai/Documents/workspace';
    const LOG_PATH      = self::LOG_DIRECTORY . '/app.log';
    const CHANNEL_NAME  = 'qingtai';

    private static $instance = null;

    public static function debug($message, array $context = [])
    {
        return self::instance()->debug($message, $context);
    }

    public static function info($message, array $context = [])
    {
        return self::instance()->info($message, $context);
    }

    public static function notice($message, array $context = [])
    {
        return self::instance()->notice($message, $context);
    }

    public static function warn($message, array $context = [])
    {
        return self::instance()->warn($message, $context);
    }

    public static function error($message, array $context = [])
    {
        return self::instance()->error($message, $context);
    }

    private static function instance()
    {
        if (null === self::$instance) {
            $backupLogPath = self::LOG_DIRECTORY . '/' . date('Ym', strtotime('-1 month')) . '.log';
            if (!file_exists(self::LOG_PATH)) {
                @touch($backupLogPath);
            } else {
                if (!file_exists($backupLogPath)) {
                    @rename(self::LOG_PATH, $backupLogPath);
                }
            }
            $getClientIp = function () {
                if (isset($_SERVER['HTTP_CLIENT_IP']) && array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
                    $ip = $_SERVER['HTTP_CLIENT_IP'];
                } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
                    $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                    $ips = array_map('trim', $ips);
                    $ip  = $ips[0];
                } else {
                    $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
                }

                $ip = filter_var($ip, FILTER_VALIDATE_IP);
                return ($ip === false) ? '0.0.0.0' : $ip;
            };
            $clientIp = $getClientIp();
            $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http';

            $getServer = function ($name, $default = '') {
                return !empty($_SERVER[$name]) ? $_SERVER[$name] : $default;
            };
            $logger = new MonologLogger(self::CHANNEL_NAME);
            $logger->pushProcessor(function ($record) use ($getServer, $clientIp, $scheme) {
                $record['extra'] = [
                    'account_id'         => defined('ACCOUNT_ID') ? ACCOUNT_ID : 0,
                    'request_method'     => $getServer('REQUEST_METHOD'),
                    'request_scheme'     => $scheme,
                    'server_name'        => $getServer('SERVER_NAME'),
                    'request_url'        => sprintf('%s://%s%s', $scheme, $getServer('SERVER_NAME'), urldecode($getServer('REQUEST_URI'))),
                    'request_uri'        => urldecode($getServer('REQUEST_URI')),
                    'query_string'       => urldecode($getServer('QUERY_STRING')),
                    'request_body'       => urldecode(http_build_query($_POST)),
                    'server_addr'        => $getServer('SERVER_ADDR'),
                    'server_port'        => $getServer('SERVER_PORT'),
                    'remote_addr'        => $getServer('REMOTE_ADDR'),
                    'client_ip'          => $clientIp,
                    'request_time'       => $getServer('REQUEST_TIME'),
                    'request_time_float' => $getServer('REQUEST_TIME_FLOAT'),
                    'http_user_agent'    => $getServer('HTTP_USER_AGENT'),
                    'http_referer'       => $getServer('HTTP_REFERER'),
                ];
                return $record;
            });
            $streamHandler = new StreamHandler(self::LOG_PATH);
            $streamHandler->setFormatter(new JsonFormatter());
            $logger->pushHandler($streamHandler);
            if (IS_DEBUG) {
                $logger->pushHandler(new FirePHPHandler());
            }
            self::$instance = $logger;
        }
        return self::$instance;
    }
}
